package com.ruoyi.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.entity.ClientUser;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.core.domain.BatchClientUserSummary;
import com.ruoyi.core.domain.ClientProduct;
import com.ruoyi.core.domain.ClientUserProductRelation;
import com.ruoyi.core.domain.SegmentTimeUnit;
import com.ruoyi.core.domain.custombean.*;
import com.ruoyi.core.mapper.BatchClientUserSummaryMapper;
import com.ruoyi.core.mapper.ClientProductMapper;
import com.ruoyi.core.mapper.ClientUserProductRelationMapper;
import com.ruoyi.core.service.BatchClientUserSummaryService;
import com.ruoyi.core.service.ClientUserService;
import com.ruoyi.core.util.CharAndNumberRandomGenerator;
import com.ruoyi.core.vo.BatchClientUserCreateOperationVO;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.system.mapper.ClientUserMapper;
import io.jsonwebtoken.lang.Assert;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;

/**
 * @Description:
 * @Company: 北京卡拉卡尔股份技术有限公司
 * @Author: Darren Ho
 * @Date: 10/16/2020 17:14
 */
@Service
public class BatchClientUserSummaryServiceImpl implements BatchClientUserSummaryService {

    protected final Logger logger = LoggerFactory.getLogger(BatchClientUserSummaryServiceImpl.class);

    @Autowired
    private ClientUserMapper clientUserMapper;

    @Autowired
    private ClientUserProductRelationMapper clientUserProductRelationMapper;

    @Autowired
    private BatchClientUserSummaryMapper batchClientUserSummaryMapper;

    @Autowired
    private ClientProductMapper clientProductMapper;

    @Autowired
    private ExecutorService concurrencyExecutorThreadPool;

    @Autowired
    private ClientUserService clientUserService;

    @Transactional
    @Override
    public Boolean create(BatchClientUserCreateOperationVO batchClientUserCreateOperationVO) {

        if (BatchClientUserCreateOperationVO.OperationType.SINGLE == batchClientUserCreateOperationVO.getOperationType()) {

            if (clientUserMapper.findByUsername(batchClientUserCreateOperationVO.getUsername()) != null) {
                String message = String.format("批量新增用户 [%s]失败,该用户名已存在", batchClientUserCreateOperationVO.getUsername());
                throw new CustomException(message);
            }
        }

        assertProductIdSetExist(batchClientUserCreateOperationVO.getProductIds());


        logger.info("生成用户开始");
        Date nowDate = DateUtils.getNowDate();

        BatchClientUserSummary batchClientUserSummary = new BatchClientUserSummary();
        batchClientUserSummary.setCreateBy(SecurityUtils.getUsername());
        batchClientUserSummary.setTimeUnit(SegmentTimeUnit.DAY);
        batchClientUserSummary.setCreateTime(nowDate);
        batchClientUserSummary.setSegment(batchClientUserCreateOperationVO.getSegment());
        batchClientUserSummary.setProductIds(JSON.toJSONString(batchClientUserCreateOperationVO.getProductIds()));
        batchClientUserSummary.setRemark(batchClientUserCreateOperationVO.getRemark());
        if (BatchClientUserCreateOperationVO.OperationType.SINGLE == batchClientUserCreateOperationVO.getOperationType()) {
            batchClientUserSummary.setQuantity(1L);
        } else {
            batchClientUserSummary.setQuantity(batchClientUserCreateOperationVO.getBatchUser());
        }

        List<ClientUser> clientUsers = new ArrayList<>();
        if (BatchClientUserCreateOperationVO.OperationType.SINGLE == batchClientUserCreateOperationVO.getOperationType()) {
            ClientUser user = new ClientUser();
            String username = batchClientUserCreateOperationVO.getUsername();
            user.setUsername(username);
            user.setNickName(username);
            String rawPassword = batchClientUserCreateOperationVO.getPassword();
            user.setRawPassword(rawPassword);
            user.setCreateTime(nowDate);
            user.setCreateBy(SecurityUtils.getUsername());
            clientUsers.add(user);
        } else {
            for (int i = 0; i < batchClientUserCreateOperationVO.getBatchUser(); i++) {
                ClientUser user = new ClientUser();
                String usernameRandom = getUsernameRandom();
                user.setUsername(usernameRandom);
                user.setNickName(usernameRandom);
                String rawPassword = CharAndNumberRandomGenerator.generate(6);
                user.setRawPassword(rawPassword);
//                user.setPassword(SecurityUtils.encryptPassword(rawPassword));
                user.setCreateTime(nowDate);
                user.setCreateBy(SecurityUtils.getUsername());
                clientUsers.add(user);
            }
        }
        logger.info("生成用户结束");
        BatchClientUserSummaryParam param = new BatchClientUserSummaryParam();
        param.setBatchClientUserSummary(batchClientUserSummary);
        param.setClientUsers(clientUsers);

        param.setProductIds(batchClientUserCreateOperationVO.getProductIds());
        param.setSegment(batchClientUserCreateOperationVO.getSegment());
        param.setTimeUnit(batchClientUserCreateOperationVO.getTimeUnit());
        param.setNow(nowDate);
        param.setRemark(batchClientUserCreateOperationVO.getRemark());
        doCreate(param,batchClientUserCreateOperationVO.getCodeIds());

        return true;
    }


    @Override
    public List<BatchClientUserSummary> findBatchClientUserSummary(BatchClientUserSummary batchClientUserSummary) {
        return batchClientUserSummaryMapper.findByBatchClientUserSummary(batchClientUserSummary);
    }

    @Override
    public List<BatchClientUserSummary> findByIdSet(Long[] ids) {
        return batchClientUserSummaryMapper.findByIdSet(ids);
    }

    @Override
    public Boolean deleteByIdSet(Long[] ids) {

        batchClientUserSummaryMapper.deleteByIdSet(ids);

        return true;
    }

    @Override
    public List<ClientUserBatchQueryResult> findBatchClientUser(ClientUserBatchQuery clientUserBatchQuery) {
        return batchClientUserSummaryMapper.findBatchClientUser(clientUserBatchQuery);
    }

    @Override
    public List<ClientUserBatchQueryResult> findClientUserByUserIdSet(Long[] ids) {
        return batchClientUserSummaryMapper.findClientUserByUserIdSet(ids);
    }

    @Override
    public Boolean updateStatusToDelete(Long id) {
        batchClientUserSummaryMapper.updateStatus(id,-1);
        return true;
    }

    @Override
    public List<BatchProductResult> getPermissionList(Long id) {
        Assert.notNull(id, "参数缺失");

        BatchClientUserSummary summary = batchClientUserSummaryMapper.findById(id);
        Assert.isTrue(summary != null && summary.getProductIds() != null, "查询失败,异常数据");

        //获取权限id集合
        List<Long> productIds = JSON.parseObject(summary.getProductIds(), new TypeReference<List<Long>>() {
        });

        //获取对应的昵称
        List<ClientProduct> productList = clientProductMapper.selectByIds(productIds);

        List<BatchProductResult> resultList = new ArrayList<>();
        productList.forEach(item -> {
            BatchProductResult result = new BatchProductResult();
            result.setProductName(item.getName());
            resultList.add(result);
        });

        return resultList;
    }

    private void doCreate(BatchClientUserSummaryParam param,List<Long> codeIds) {
        BatchClientUserSummary batchClientUserSummary = param.getBatchClientUserSummary();
        List<ClientUser> clientUsers = param.getClientUsers();

        batchClientUserSummaryMapper.insert(batchClientUserSummary);
        Long batchId = batchClientUserSummary.getId();
        clientUsers.forEach(item -> {
            item.setBatchId(batchId);
            item.setRemark(param.getRemark());
        });

        clientUserMapper.batchInsert(clientUsers);

        //3、 写入 客户端 用户有效期
        List<ClientUserProductRelation> clientUserProductRelations = new ArrayList<>();
        clientUsers.forEach(clientUser -> {
            param.getProductIds().forEach(productId -> {
                ClientUserProductRelation clientUserProductRelation = new ClientUserProductRelation();
                clientUserProductRelation.setUserId(clientUser.getId());
                clientUserProductRelation.setProductId(productId);
                clientUserProductRelations.add(clientUserProductRelation);
            });
        });


        clientUserProductRelationMapper.batchInsert(clientUserProductRelations);

        logger.info("持久化用户结束");

        // 更新创建用户的密码

        clientUsers.forEach(item -> {
            Runnable task = () -> {
                item.setPassword(SecurityUtils.encryptPassword(item.getRawPassword()));
                clientUserMapper.update(item);
            };
            concurrencyExecutorThreadPool.submit(task);
        });

        for (Long codeId : codeIds) {
            //cookie分配
            if(codeId != null && codeId != -1L){
                clientUsers.forEach(item -> {
                    Runnable task = () -> {
                        clientUserService.updateCkConfig(new UpdateCkConfigParams(item.getId(),codeId));
                    };
                    concurrencyExecutorThreadPool.submit(task);
                });
            }
        }
    }

    private String getUsernameRandom() {
        String username = CharAndNumberRandomGenerator.generate(6) + "@163.com";
        if (clientUserMapper.findByUsername(username) != null) {
            return getUsernameRandom();
        } else {
        return username;
        }
    }


    private void assertProductIdSetExist(List<Long> productIds) {
        for (Long productId : productIds) {
            if (clientProductMapper.selectClientProductById(productId) == null) {
                String message = String.format("批量新增用户失败,用户权限客户端产品不存在,产品id[%s]", productId);
                throw new CustomException(message);
            }

        }

    }

}
